use crate::app::core::start;
use crate::config::Config;
use std::future::Future;
use std::path::Path;
use std::pin::Pin;
use wd_run::Context;

pub struct Run {
    channel: (async_channel::Sender<()>, async_channel::Receiver<()>),
}
impl Run {
    pub fn cmd() -> wd_run::CmdInfo {
        wd_run::CmdInfo::new("run", "run core").add(
            "c",
            "./src/config/config.toml",
            "config file path",
        )
    }
    pub fn new() -> (Self, super::Exit) {
        let channel = async_channel::unbounded::<()>();
        return (
            Run {
                channel: channel.clone(),
            },
            super::Exit::new(channel),
        );
    }
}

impl Run {
    #[allow(dead_code)]
    async fn load_config(&self, ctx: Context) {
        let path = ctx.copy::<_, String>("c").await.unwrap();
        let cfg = crate::config::load_config(path.clone());
        wd_log::log_info_ln!("配置文件：{}\n -->{}", path, cfg.json_show())
    }
}

impl wd_run::EventHandle for Run {
    fn handle(&self, ctx: Context) -> Pin<Box<dyn Future<Output = Context> + Send>> {
        let chan = self.channel.clone();
        Box::pin(async move {
            let rt = RunTime::new(ctx.copy::<_, String>("c").await.unwrap(), chan);
            rt.launch().await;
            return ctx;
        })
    }
}

struct RunTime {
    config: Config,
    channel: (async_channel::Sender<()>, async_channel::Receiver<()>),
}
impl RunTime {
    fn new(
        path: impl AsRef<Path>,
        channel: (async_channel::Sender<()>, async_channel::Receiver<()>),
    ) -> Self {
        let config = crate::config::load_config(path);
        Self { config, channel }
    }
    async fn launch(self) {
        //todo
        wd_log::log_info_ln!("config:{}", self.config.json_show());
        //todo 初始化日志
        let mut app = start(self.config).await.expect("服务启动失败");
        let _ = self.channel.1.recv().await;
        wd_log::log_info_ln!("接收到退出信号，开始停止所有服务...");
        app.close().await;
        wd_log::log_info_ln!("全部服务已停止！！！程序成功退出");
        let _ = self.channel.0.send(()).await;
    }
}
